namespace WP7Contrib.Caching
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    internal sealed class SerializationNode
    {
        private const string ROOT_NODE = "<ROOT>";

        private readonly SerializationNode parent;
        private readonly string name;
        private readonly object value;
        
        private readonly IList<SerializationNode> children;

        private SerializationState state;

        public SerializationNode(object root)
        {
            this.parent = null;
            this.name = ROOT_NODE;
            this.value = root;

            this.children = new List<SerializationNode>();
        }

        internal SerializationNode(SerializationNode parent, string name, object value)
        {
            this.parent = parent;
            this.name = name;
            this.value = value;

            this.children = new List<SerializationNode>();
        }
        public SerializationNode Root
        {
            get
            {
                if (!this.HasParent)
                {
                    return this;
                }
                else
                {
                    var current = this;
                    while(true)
                    {
                        var tmp = current.Parent;
                        if (tmp == null)
                        {
                            return current;
                        }
                        current = tmp;
                    }
                }
            }
        }

        public SerializationNode Parent
        {
            get { return parent; }
        }
        
        public string Name
        {
            get { return name; }
        }

        public object Value
        {
            get { return value; }
        }
        
        public IList<SerializationNode> Children
        {
            get { return children; }
        }

        public bool HasParent
        {
            get { return this.Parent != null; }
        }
        
        public bool HasValue
        {
            get { return this.Value != null; }
        }

        public bool HasChildren
        {
            get { return this.Children.Count != 0; }
        }

        public SerializationState State
        {
            get
            {
                return this.state;
            }
            set
            {
                this.state = value;
            }
        }

        public bool CanBeSerialized
        {
            get { return this.State == SerializationState.Failed; }
        }
        
        public SerializationNode AddChild(string name, object value)
        {
            var childNode = new SerializationNode(this, name, value);
            this.children.Add(childNode);

            return childNode;
        }

        public bool ContainsType(Type type)
        {
            if (this.value.GetType() == type)
            {
                return true;
            }

            return this.children.Where(c => c.ContainsType(type)).Count() != 0;
        }
    }
}